package net.sharpf2.api.world;

import java.awt.Point;
import java.util.ArrayList;
import net.sharpf2.api.Globals;
import net.sharpf2.api.Methods;
import net.sharpf2.api.types.Content;
import net.sharpf2.api.util.Mathematics;
import net.sharpf2.sfcore.client.GroundItem;
import net.sharpf2.sfcore.client.Node;
import net.sharpf2.sfcore.client.NodeList;
import net.sharpf2.sfcore.client.NodeListCache;

/**
 *
 * @author Rick van Biljouw
 */
public class GroundItems {

    /**
     * Returns all ground items in the region
     * @return ArrayList<Content<GroundItem>>
     */
    public static ArrayList<Content<GroundItem>> getAll() {
        ArrayList<Content<GroundItem>> items = new ArrayList<Content<GroundItem>>();
        Point playerPosition = Methods.getMyPlayer().getContent().getWorldPosition();

        for (int x = 0; x < 104; x++) {
            for (int y = 0; y < 104; y++) {
                items.addAll(getItemsAt(new Point(Globals.CLIENT.getBaseX() + x, Globals.CLIENT.getBaseY() + y)));
            }
        }
        return items;
    }

    /**
     * Returns all ground items within specific radius
     * @param   radius  Radius.
     * @return  ArrayList<Content<GroundItem>>
     */
    public static ArrayList<Content<GroundItem>> getAll(int radius) {
        ArrayList<Content<GroundItem>> items = new ArrayList<Content<GroundItem>>();
        for (Content<GroundItem> item : getAll()) {
            if (Mathematics.distanceToPlayer(item.getContent().getWorldPosition()) < radius) {
                items.add(item);
            }
        }
        return items;
    }

    /**
     * Returns the ground items at a certain tile.
     * @param   tile    Tile.
     * @return  ArrayList<Content<GroundItem>>
     */
    public static ArrayList<Content<GroundItem>> getItemsAt(Point tile) {
        ArrayList<Content<GroundItem>> items = new ArrayList<Content<GroundItem>>();
        Node[] nodes = Globals.CLIENT.getGroundItemCache().getNodes();
        int id = tile.x | tile.y << 14 | Globals.CLIENT.getPlane() << 28;
        int index = id & (nodes.length - 1);

        Node tail = nodes[index];
        Node current = tail.getNext();
        NodeList nodeList = null;

        while (!tail.getObject().equals(current.getObject()) && !Thread.currentThread().isInterrupted()) {
            if (current.getId() == id) {
                nodeList = new NodeListCache(Globals.METHODS, current.getObject()).getNodeList();
                break;
            } else {
                current = current.getNext();
            }
        }

        if (nodeList != null) {
            tail = nodeList.getFirst();
            current = tail.getNext();

            while (!tail.getObject().equals(current.getObject()) && !Thread.currentThread().isInterrupted()) {
                GroundItem item = new GroundItem(Globals.METHODS, current.getObject(), tile);
                if (item.getId() > 0) {
                    items.add(new Content<GroundItem>(item));
                }

                current = current.getNext();
            }
        }

        return items;
    }

    /**
     * Returns the nearest matching ground item by id
     * @param   ids Item ids.
     * @return  Content<GroundItem>
     */
    public static Content<GroundItem> getNearest(int... ids) {
        Content<GroundItem> best = null;
        int dist = 9999;
        for (Content<GroundItem> item : getAll()) {
            for (int id : ids) {
                int nDist = 0;
                if (item.getContent().getId() == id && ((nDist = Mathematics.distanceToPlayer(item.getContent().getWorldPosition()))) < dist) {
                    dist = nDist;
                    best = item;
                    System.out.println("Found item: "+item.getContent().getId());
                }
            }
        }
        return best;
    }
}
